package sz;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.FloatControl;

/** 
  * Play.java
  * <p>
  * A simple class that plays audio from given file names.
  * <p>
  * Uses the Java Sound SourceDataLine interface to stream the sound. 
  * Converts compressed encodings (ALAW, ULAW, MP3) to PCM.
  * @author Dan Becker, beckerdo@io.com
  */
public class MP3Test {
   /** Plays audio from given file names. */
   public static void main( String [] args ) {
      playAudioFile("Castle2_DraculaBattle.mp3");
   
      // Must exit explicitly since audio creates non-daemon threads.
      //System.exit( 0 );
   } // main
 
   /** Play audio from the given file name. */
   public static void playAudioFile( String fileName ) {
	   System.out.println("playAudioFile "+fileName);
      File soundFile = new File( fileName );

      try {
         // Create a stream from the given file.
         // Throws IOException or UnsupportedAudioFileException
         AudioInputStream audioInputStream = AudioSystem.getAudioInputStream( soundFile );
         // AudioSystem.getAudioInputStream( inputStream ); // alternate audio stream from inputstream
         playAudioStream( audioInputStream );
      } catch ( Exception e ) {
         System.out.println( "Problem with file " + fileName + ":" );
         e.printStackTrace();
      }
   } // playAudioFile

   /** Plays audio from the given audio input stream. */
   public static void playAudioStream( AudioInputStream audioInputStream ) {
      // Audio format provides information like sample rate, size, channels.
      AudioFormat audioFormat = audioInputStream.getFormat();
      System.out.println( "Play input audio format=" + audioFormat );

      // Convert compressed audio data to uncompressed PCM format.
      if ( audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED ) {
      // if ((audioFormat.getEncoding() != AudioFormat.Encoding.PCM) ||
      //     (audioFormat.getEncoding() == AudioFormat.Encoding.ALAW) || 
      //     (audioFormat.getEncoding() == AudioFormat.Encoding.MP3)) {
         AudioFormat newFormat = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED, 
            audioFormat.getSampleRate(),
            16,
            audioFormat.getChannels(),
            audioFormat.getChannels() * 2,
            audioFormat.getSampleRate(),
            false );
         System.out.println( "Converting audio format to " + newFormat );
         AudioInputStream newStream = AudioSystem.getAudioInputStream( newFormat, audioInputStream );
         audioFormat = newFormat;
         audioInputStream = newStream;
      }
  
      // Open a data line to play our type of sampled audio.
      // Use SourceDataLine for play and TargetDataLine for record.
      DataLine.Info info = new DataLine.Info( SourceDataLine.class, audioFormat );
      if ( !AudioSystem.isLineSupported( info ) ) {
         System.out.println( "Play.playAudioStream does not handle this type of audio on this system." );
         return;
      }

      try {
         // Create a SourceDataLine for play back (throws LineUnavailableException).  
         SourceDataLine dataLine = (SourceDataLine) AudioSystem.getLine( info );
         // System.out.println( "SourceDataLine class=" + dataLine.getClass() );

         // The line acquires system resources (throws LineAvailableException).
         dataLine.open( audioFormat );
   
         // Adjust the volume on the output line.
         if( dataLine.isControlSupported( FloatControl.Type.MASTER_GAIN ) ) {
            FloatControl volume = (FloatControl) dataLine.getControl( FloatControl.Type.MASTER_GAIN );
            //volume.setValue( 100.0F );
            
            volume.setValue(volume.getMaximum());
         }

         // Allows the line to move data in and out to a port.
         dataLine.start();
   
         // Create a buffer for moving data from the audio stream to the line.   
         int bufferSize = (int) audioFormat.getSampleRate() * audioFormat.getFrameSize();
         byte [] buffer = new byte[ bufferSize ];
   
         // Move the data until done or there is an error.
         try {
            int bytesRead = 0;
            while ( bytesRead >= 0 ) {
               bytesRead = audioInputStream.read( buffer, 0, buffer.length );
               if ( bytesRead >= 0 ) {
                  // System.out.println( "Play.playAudioStream bytes read=" + bytesRead +
                  //    ", frame size=" + audioFormat.getFrameSize() + ", frames read=" + bytesRead / audioFormat.getFrameSize() );
                  // Odd sized sounds throw an exception if we don't write the same amount.
                  int framesWritten = dataLine.write( buffer, 0, bytesRead );
               }
            } // while
         } catch ( IOException e ) {
            e.printStackTrace();
         }

         System.out.println( "Play.playAudioStream draining line." );
         // Continues data line I/O until its buffer is drained.
         dataLine.drain();
   
         System.out.println( "Play.playAudioStream closing line." );
         // Closes the data line, freeing any resources such as the audio device.
         dataLine.close();
      } catch ( LineUnavailableException e ) {
         e.printStackTrace();
      }
   } // playAudioStream
} // Play